﻿using Emgu.CV;
using Emgu.CV.Structure;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FormMainSSID
{
    //一个文件夹下的所有切片的信息，将其存为json
    public class Layers
    {
        public Dictionary<int, Layer> dict_layer { get; set; }
    }

    //一层切片的设置信息
    public class Layer
    {
        public string path_raw { get; set; }
        public string path_config { get; set; }
        public int scale_raw { get; set; }
        public int layer { get; set; }
        public int hang { get; set; }
        public int lie { get; set; }
        public string description { get; set; }
        public int dimensions { get; set; }
        public string[] dimension { get; set; }
        public List<Dictionary<Point, string>> dictdim { get; set; }
        public List<List<int[]>> Position { get; set; }
        public string path_fullsnp { get; set; }
        public int[] pos { get; set; }
    }

    /// <summary>
    /// 统领本layer的所有尺度dimension，与窗口进程进行交流
    /// </summary>
    public class DisplayLayer
    {
        public Layer layer;
        public List<DisplayDim> displaydim = new List<DisplayDim>();

        public List<Task> task = new List<Task>();
        public List<DimTaskInformation> dimtaskimformation = new List<DimTaskInformation>();

        public Point Mid_img = new Point();

        public DisplayLayer(Layer layer1, Image<Gray, byte> snp)
        {
            layer = layer1;
            for(int i = 0; i < layer.dimensions; i++)
            {
                displaydim.Add(new DisplayDim(this, i));
                dimtaskimformation.Add(new DimTaskInformation());
                task.Add(new Task(() => Calculate.DimTask(this, i)));
                task[i].Start();
                Thread.Sleep(100);
                if (i == 0)
                {
                    displaydim[i].snp = snp;
                    displaydim[i].rect = new Rectangle(0, 0, snp.Width, snp.Height);
                }
            }
            //task[1].Start();
        }

        public move_data MouseWheel(object sender, MouseEventArgs e, Size box_size, Size form_size)
        {
            move_data data = new move_data();
            int running = displaydim.FindIndex(item => item.shift.Equals(true));
            data = displaydim[running].Mousewheel(sender, e, box_size, form_size, 0.6);
            Console.WriteLine(running.ToString());
            if(displaydim[running].shift_in)
            {
                if (running < layer.dimensions - 1)
                {
                    Console.WriteLine(dimtaskimformation[running + 1].status.ToString());
                    if (dimtaskimformation[running + 1].status == TaskStatus.RanToCompletion && Mid_img.Equals(dimtaskimformation[running + 1].mid))
                    {
                        displaydim[running + 1].Init(dimtaskimformation[running + 1], displaydim[running].GetInformation());
                        displaydim[running].Close();
                    }
                }
            }
            else if(displaydim[running].shift_out)
            {
                if (running > 1)
                {
                    Console.WriteLine(dimtaskimformation[running - 1].status.ToString());
                    if (dimtaskimformation[running - 1].status == TaskStatus.RanToCompletion)
                    {
                        displaydim[running - 1].Init(dimtaskimformation[running - 1], displaydim[running].GetInformation());
                        displaydim[running].Close();
                    }
                }
                else if (running == 1)
                {
                    displaydim[running - 1].Init(dimtaskimformation[running - 1], displaydim[running].GetInformation());
                    displaydim[running].Close();
                }
            }
            return data;
        }

        public move_data MouseMove(object sender, MouseEventArgs e, Size box_size, move_data data1)
        {
            move_data data = new move_data();

            data = displaydim[displaydim.FindIndex(item => item.shift.Equals(true))].Mousemove(sender, e, box_size, data1.x, data1.y);
;
            return data;
        }
    }

    /// <summary>
    /// 包含本尺度的所有信息，包括图片，矩形等。
    /// </summary>
    public class DisplayDim
    {
        public Image<Gray, byte> snp = new Image<Gray, byte>(0, 0);
        public Rectangle rect = new Rectangle(0, 0, 0, 0);
        DisplayLayer displaylayer;

        int self_index;

        public bool shift = false;
        bool box = false;

        public bool shift_in = false;
        public bool shift_out = false;

        static double scale_win;
        int widr, heir;
        double box_level = 1.0;
        double level = 1.0;

        Point start = new Point();
        Point end = new Point();
        int[] pos = new int[2];

        public DisplayDim(DisplayLayer dis1, int i)
        {
            displaylayer = dis1;
            self_index = i;
            if (self_index == 0)
            {
                shift = true;
                box = true;
                start = new Point(0, 0);
                end = new Point(displaylayer.layer.hang - 1, displaylayer.layer.lie - 1);
                pos = displaylayer.layer.pos;
            }
        }

        public void Init(DimTaskInformation dimtaskinformation, ShiftInformation shiftinformation)
        {
            rect.Width = (int)(shiftinformation.rect.Width * (int.Parse(displaylayer.layer.dimension[self_index]) / (double)(int.Parse(displaylayer.layer.dimension[shiftinformation.index]))));
            rect.Height = (int)(shiftinformation.rect.Height * (int.Parse(displaylayer.layer.dimension[self_index]) / (double)(int.Parse(displaylayer.layer.dimension[shiftinformation.index]))));
            if (self_index > 0)
            {
                snp = dimtaskinformation.snp;
                start = dimtaskinformation.start;
                end = dimtaskinformation.end;
                pos = dimtaskinformation.pos;
                widr = snp.Width;
                heir = snp.Width * rect.Height / rect.Width;
            }
            rect.X = (int)((((shiftinformation.rect.X - shiftinformation.pos[0]) * ((double)(displaylayer.layer.scale_raw) / int.Parse(displaylayer.layer.dimension[shiftinformation.index]))) -
                        (displaylayer.layer.Position[start.X][start.Y][0] - displaylayer.layer.Position[shiftinformation.start.X][shiftinformation.start.Y][0])) * (int.Parse(displaylayer.layer.dimension[self_index]) / (double)(displaylayer.layer.scale_raw))) +
                        pos[0];
            rect.Y = (int)((((shiftinformation.rect.Y - shiftinformation.pos[1]) * ((double)(displaylayer.layer.scale_raw) / int.Parse(displaylayer.layer.dimension[shiftinformation.index]))) -
                          (displaylayer.layer.Position[start.X][start.Y][1] - displaylayer.layer.Position[shiftinformation.start.X][shiftinformation.start.Y][1])) * (int.Parse(displaylayer.layer.dimension[self_index]) / (double)(displaylayer.layer.scale_raw))) +
                          pos[1];
            level = (double)rect.Width / widr;
            shift = true;
        }

        public void Close()
        {
            shift = false;
            shift_in = false;
            shift_out = false;
        }

        public ShiftInformation GetInformation()
        {
            ShiftInformation shiftinformation = new ShiftInformation();
            shiftinformation.index = self_index;
            shiftinformation.rect = rect;
            shiftinformation.start = start;
            shiftinformation.end = end;
            shiftinformation.pos = pos;
            return shiftinformation;
        }

        public move_data Mousewheel(object sender, MouseEventArgs e, Size box_size, Size form_size, double prop1)
        {
            move_data data1 = new move_data();
            Size rect_size_before = new Size();
            int x, y, poi_y;
            int box_height;
            double proportion, prop;
            
            prop = prop1;
            box_height = box_size.Height;
            poi_y = 0;

            rect_size_before.Width = rect.Width;
            rect_size_before.Height = rect.Height;
            if (box)
            {
                if (e.Delta > 0)
                {
                    box_level = box_level - 0.1;
                }
                else if (e.Delta < 0)
                {
                    box_level = box_level + 0.1;

                    if (box_level > 1.0)
                    {
                        box_level = 1.0;
                    }
                }
                
                rect.Width = (int)(snp.Width * box_level);
                box_height = box_size.Width * rect.Height / rect.Width;
                proportion = (double)rect.Width / rect_size_before.Width;

                x = (int)((e.X * rect_size_before.Width / box_size.Width) * (1 - proportion)) + rect.X;
                y = 0;
                //poi_y  = form.imageBoxLeft.Location.Y - ((box_height - form.imageBoxLeft.Height) / 2);
                poi_y = (form_size.Height - box_height) / 2;
                if(poi_y < 0)
                {
                    poi_y = 0;
                }
                if (x < 0)
                {
                    x = 0;
                }

                if (x + (int)(snp.Width * box_level) > snp.Width)
                {
                    x = snp.Width - (int)(snp.Width * box_level);
                }
                if (box_height >= form_size.Height)
                {
                    box_height = form_size.Height;
                    rect.Height = rect.Width * box_height / box_size.Width;
                    widr = rect.Width;
                    heir = rect.Height;
                    scale_win = (double)rect.Height / rect.Width;
                    box = false;
                }
                if (box_level == 1.0)
                {
                    rect.Height = snp.Height;
                }
                
                rect.X = x;
                rect.Y = y;

                data1.x = box_height;
                data1.y = poi_y;
                //rect = new Rectangle(xr, yr, widr, heir);
                data1.img = snp.GetSubRect(rect);
                return data1;
            }
            else
            {
                if (e.Delta > 0)
                {
                    level = level - 0.05;

                    if (level < 0.5)
                    {
                        if (level < 0.1)
                        {
                            level = 0.1;
                        }
                    }
                }
                else if (e.Delta < 0)
                {
                    level = level + 0.05;
                    if (level > 1.0)
                    {
                        level = 1.0;
                    }
                }

                rect.Width = (int)(widr * level);
                rect.Height = (int)(widr * level * scale_win);
                proportion = (double)rect.Width / rect_size_before.Width;

                x = (int)((e.X * rect_size_before.Width / box_size.Width) * (1 - proportion)) + rect.X;
                if (x < 0)
                {
                    x = 0;
                }
                y = (int)((e.Y * rect_size_before.Height / box_size.Height) * (1 - proportion)) + rect.Y;
                if (y < 0)
                {
                    y = 0;
                }
                if (x + (int)(widr * level) > snp.Width)
                {
                    x = snp.Width - (int)(widr * level);
                }
                if (y + (int)(widr * level * scale_win) > snp.Height)
                {
                    y = snp.Height - (int)(widr * level * scale_win);
                }
                rect.X = x;
                rect.Y = y;
                if (level == 1.0 /*&& rect.Height == snp.Height*/)
                {
                    if (self_index == 0)
                    {
                        if(rect.Height < snp.Height)
                        {
                            rect.Height = snp.Height;
                            rect.Y = 0;
                            box = true;
                        }
                    }
                }
                displaylayer.Mid_img = Calculate.Scan(displaylayer.layer.Position, (int)(((rect.X + (rect.Width / 2)) - pos[0]) * ((double)displaylayer.layer.scale_raw / int.Parse(displaylayer.layer.dimension[self_index]))) + displaylayer.layer.Position[start.X][start.Y][0],
                                                                (int)(((rect.Y + (rect.Height / 2)) - pos[1]) * ((double)displaylayer.layer.scale_raw / int.Parse(displaylayer.layer.dimension[self_index]))) + displaylayer.layer.Position[start.X][start.Y][1]);
                //Console.WriteLine(displaylayer.Mid_img.ToString());
                if ((rect.Width * rect.Height) <= (box_size.Width * box_size.Height * prop))
                {
                    shift_in = true;
                }
                else if (((rect.Width * rect.Height) >= (snp.Width * snp.Height * 0.9) || rect.Width >= snp.Width || rect.Height >= snp.Height) && self_index > 0)
                {
                    shift_out = true;
                }
                else
                {
                    shift_in = false;
                    shift_out = false;
                }
                //rect = new Rectangle(xr, yr, widr, heir);
                data1.x = box_height;
                data1.y = poi_y;
                //rect = new Rectangle(xr, yr, widr, heir);
                data1.img = snp.GetSubRect(rect);
                return data1;
                //label1.Text = level_256.ToString();
                //label4.Text = "256";

            }
        }

        public move_data Mousemove(object sender, MouseEventArgs e, Size box_size, int xm, int ym)
        {
            move_data data;
            int x, y;

            x = rect.X - (int)(((e.X - xm) * rect.Width / box_size.Width));
            y = rect.Y - (int)(((e.Y - ym) * rect.Height / box_size.Height));

            if (x < 0)
            {
                x = 0;
            }
            if ((x + rect.Width) > snp.Width)
            {
                x = rect.X;
            }

            if (y < 0)
            {
                y = 0;
            }
            if ((y + rect.Height) > snp.Height)
            {
                y = rect.Y;
            }
            displaylayer.Mid_img = Calculate.Scan(displaylayer.layer.Position, (int)(((rect.X + (rect.Width / 2)) - pos[0]) * ((double)displaylayer.layer.scale_raw / int.Parse(displaylayer.layer.dimension[self_index]))) + displaylayer.layer.Position[start.X][start.Y][0],
                                                               (int)(((rect.Y + (rect.Height / 2)) - pos[1]) * ((double)displaylayer.layer.scale_raw / int.Parse(displaylayer.layer.dimension[self_index]))) + displaylayer.layer.Position[start.X][start.Y][1]);
            data.x = e.X;
            data.y = e.Y;
            rect.X = x;
            rect.Y = y;
            data.img = snp.GetSubRect(rect);
            
            return data;
        }
    }

    public class CreatInformation
    {
        public int raw_scale;
    }

    public class DimTaskInformation
    {
        public Image<Gray, byte> snp = null;
        public Point start = new Point();
        public Point end = new Point();
        public Point mid = new Point();
        public int[] pos = new int[2];
        public TaskStatus status;
    }

    public class ShiftInformation
    {
        public int index;
        public Rectangle rect = new Rectangle(0, 0, 0, 0);
        public Point start = new Point();
        public Point end = new Point();
        public int[] pos = new int[2];
    }
    public class Offset
    {
        public string name_format { get; set; }
        public string name_extent { get; set; }
        public Dictionary<string, int> dict_foramt { get; set; }
        public string folder_path { get; set; }
        public int total_Layers { get; set; }
        public List<int> size_Layer { get; set; }
        public List<int> start_Index { get; set; }
        public int[,,,] l2rindex_array_map { get; set; }
        public int[,,,] u2dindex_array_map { get; set; }
    }

    public class Ini
    {
        private string path;

        [DllImport("kernel32")]
        private static extern bool WritePrivateProfileString(string section, string key, string val, string filePath);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer, uint nSize, string lpFileName);
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

        public Ini(string path1)
        {
            this.path = path1;
        }

        public void write(string section, string key, string value)
        {
            WritePrivateProfileString(section, key, value, path);
        }

        public string read(string section, string key)
        {
            StringBuilder temp = new StringBuilder(500);

            int i = GetPrivateProfileString(section, key, "", temp, 500, this.path);

            return temp.ToString();
        }

        public string[] Getsections()
        {
            string[] sections = new string[] { };
            uint MAX_BUFFER = 32767;

            IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));
            uint bytesReturned = Ini.GetPrivateProfileSectionNames(pReturnedString, MAX_BUFFER, path);

            if (bytesReturned != 0)
            {
                //读取指定内存的内容
                string local = Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned).ToString();

                //每个节点之间用\0分隔,末尾有一个\0
                sections = local.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
            }

            //释放内存
            Marshal.FreeCoTaskMem(pReturnedString);

            return sections;
        }

        public bool isExist()
        {
            return File.Exists(this.path);
        }
    }
    public struct move_data
    {
        public Image<Gray, byte> img;
        public int x;
        public int y;
    };
    public class Calculate
    {
        //将offset的相邻图片位置关系计算为统一的坐标信息
        public static List<List<int[]>> CalPosition(Offset offset, int layer)
        {
            List<List<int[]>> Position = new List<List<int[]>>();

            List<int[]> array = new List<int[]>();

            int[] offset2to1 = new int[2];
            int[] Spot = new int[2];
            int init_x = 0, init_y = 0;

            int offtrainx = 0;
            int offtrainy = 0;

            for (int h = 0; h < offset.size_Layer[0]; h++)
            {
                if (h == 0)
                {
                    init_x = 0;
                    init_y = 0;
                }
                else
                {
                    offset2to1[0] = offset.u2dindex_array_map[layer - 1, h - 1, 0, 0];
                    offset2to1[1] = offset.u2dindex_array_map[layer - 1, h - 1, 0, 1];

                    init_x = offset2to1[0] + init_x;
                    init_y = offset2to1[1] + init_y;
                }
                Spot[0] = init_x;
                Spot[1] = init_y;
                array.Add((int[])Spot.Clone());
                offtrainy = init_y;
                offtrainx = init_x;
                for (int i = 0; i < offset.size_Layer[1] - 1; i++)
                {
                    offset2to1[0] = offset.l2rindex_array_map[layer - 1, h, i, 0];
                    offset2to1[1] = offset.l2rindex_array_map[layer - 1, h, i, 1];

                    if (offset2to1[0] == -1 && offset2to1[1] == -1)
                    {
                        offset2to1[0] = offset.u2dindex_array_map[layer - 1, h - 1, i + 1, 0];
                        offset2to1[1] = offset.u2dindex_array_map[layer - 1, h - 1, i + 1, 1];

                        offtrainx = offset2to1[0] + Position[h - 1][i + 1][0];
                        offtrainy = offset2to1[1] + Position[h - 1][i + 1][1];
                    }
                    else
                    {
                        offtrainx = offset2to1[0] + offtrainx;
                        offtrainy = offset2to1[1] + offtrainy;
                    }

                    Spot[0] = offtrainx;
                    Spot[1] = offtrainy;
                    array.Add((int[])Spot.Clone());
                }
                Position.Add(new List<int[]>(array.ToArray()));
                array.Clear();
            }
            return Position;
        }

        //将小图片进行拼接，返回图片和第一张小图片在拼接图像的位置
        public static move_data Puzzle(Layer layer, int size, int[] start, int[] end, CancellationToken cancel = new CancellationToken())
        {
            int min_xu = 0, max_xd = 0;
            int min_yl = 0, max_yr = 0;

            int init_x = 0, init_y = 0;
            int move_x = 0, move_y = 0;

            double multi;
            Point poi = new Point();

            Rectangle re1, re2;

            move_data data;
            data.x = 0;
            data.y = 0;
            data.img = new Image<Gray, byte>(0, 0);

            multi = ((double)size / layer.scale_raw);

            min_xu = layer.Position[start[0]][start[1]][1];
            min_yl = layer.Position[start[0]][start[1]][0];
            
            for (int i = start[1]; i <= end[1]; i++)
            {
                if (min_xu > layer.Position[start[0]][i][1])
                {
                    min_xu = layer.Position[start[0]][i][1];
                }
            }
            for (int i = start[0]; i <= end[0]; i++)
            {
                if (min_yl > layer.Position[i][start[1]][0])
                {
                    min_yl = layer.Position[i][start[1]][0];
                }
            }

            max_xd = layer.Position[end[0]][start[1]][1];
            max_yr = layer.Position[start[0]][end[1]][0];

            for (int i = start[1]; i <= end[1]; i++)
            {
                if (max_xd < layer.Position[end[0]][i][1])
                {
                    max_xd = layer.Position[end[0]][i][1];
                }
            }
            for (int i = start[0]; i <= end[0]; i++)
            {
                if (max_yr < layer.Position[i][end[1]][0])
                {
                    max_yr = layer.Position[i][end[1]][0];
                }
            }

            max_xd = max_xd + layer.scale_raw;
            max_yr = max_yr + layer.scale_raw;


            Image<Gray, byte> snp = new Image<Gray, byte>((int)((max_yr - min_yl) * multi + 3), (int)((max_xd - min_xu) * multi + 3));
            Image<Gray, byte> ex1 = null;

            init_x = (int)((layer.Position[start[0]][start[1]][0] - min_yl) * multi);
            init_y = (int)((layer.Position[start[0]][start[1]][1] - min_xu) * multi);

            move_x = (int)(layer.Position[start[0]][start[1]][0] * multi) - init_x;
            move_y = (int)(layer.Position[start[0]][start[1]][1] * multi) - init_y;

            Console.WriteLine(start[0].ToString() + ",," + start[1].ToString());
            Console.WriteLine(end[0].ToString() + ",," + end[1].ToString());
            for (int i = start[0]; i <= end[0]; i++)
            {
                for (int j = start[1]; j <= end[1]; j++)
                {
                    if (cancel.IsCancellationRequested)
                    {
                        Console.WriteLine("cancel");
                        return data;
                    }
                    poi.X = i;
                    poi.Y = j;
                    //new System.Threading.Thread(delegate ()
                    //{
                    //ex1 = new Image<Gray, byte>(files[i * Form1.offset.size_Layer[1] + j]);
                    //ex1 = ex1.Resize(size, size, Emgu.CV.CvEnum.Inter.Linear);
                    ex1 = new Image<Gray, byte>(layer.dictdim[Array.IndexOf(layer.dimension, size.ToString())][poi]);
                    re1 = new Rectangle(0, 0, ex1.Width, ex1.Height);
                    CvInvoke.cvSetImageROI(ex1.Ptr, re1);
                    re2 = new Rectangle((int)(layer.Position[i][j][0] * multi - move_x), (int)(layer.Position[i][j][1] * multi - move_y), ex1.Width, ex1.Height);
                    CvInvoke.cvSetImageROI(snp.Ptr, re2);
                    CvInvoke.cvCopy(ex1.Ptr, snp.Ptr, IntPtr.Zero);
                    CvInvoke.cvResetImageROI(snp);
                    //Console.WriteLine(i.ToString() + "|" + j.ToString());
                    //}).Start();
                }
            }
            data.img = snp;
            data.x = init_x;
            data.y = init_y;
            return data;
        }

        public static Point Scan(List<List<int[]>> Position, int X, int Y)
        {
            Point poi = new Point();
            int[] spot = new int[2] { 0, 0 };
            int x, y;

            x = X;
            y = Y;
            for (int i = 0; i < Position.Count; i++)
            {
                for (int j = 0; j < Position[i].Count; j++)
                {
                    if (i == 0 && j == 0 && ((x >= Position[i][j][0] && x < Position[i][j + 1][0] && y < Position[i][j][1]) || (x <= Position[i][j][0] && y >= Position[i][j][1] && y < Position[i + 1][j][1]) || (x <= Position[i][j][0] && y < Position[i][j][1])))
                    {
                        spot[0] = i;
                        spot[1] = j;
                        break;
                    }
                    else if (i == 0 && y < Position[i][j][1])
                    {
                        if ((j == Position[i].Count - 1 && x >= Position[i][j][0]) || (x >= Position[i][j][0] && x < Position[i][j + 1][0]))
                        {
                            spot[0] = i;
                            spot[1] = j;
                            break;
                        }
                    }
                    else if (j == 0 && x <= Position[i][j][0])
                    {
                        if ((i == Position.Count - 1 && y >= Position[i][j][1]) || (y >= Position[i][j][1] && y < Position[i + 1][j][1]))
                        {
                            spot[0] = i;
                            spot[1] = j;
                            break;
                        }

                    }
                    else if ((j == Position[i].Count - 1 && x >= Position[i][j][0]) || (x >= Position[i][j][0] && x < Position[i][j + 1][0]))
                    {
                        if ((i == Position.Count - 1 && y >= Position[i][j][1]) || (y >= Position[i][j][1] && y < Position[i + 1][j][1]))
                        {
                            spot[0] = i;
                            spot[1] = j;
                            break;
                        }
                    }
                }
            }
            poi.X = spot[0];
            poi.Y = spot[1];
            return poi;
        }

        public static void DimTask(DisplayLayer displaylayer, int index)
        {
            var tokenSource = new CancellationTokenSource();
            var cancel = tokenSource.Token;
            Task<move_data> task_puzzle = null;

            move_data data = new move_data();

            int hang = 5;
            int lie = 7;
            int[] start = new int[2];
            int[] end = new int[2];
            Point mid = new Point();

            mid.X = displaylayer.Mid_img.X;
            mid.Y = displaylayer.Mid_img.Y;

            Console.WriteLine(index.ToString());

            while (true)
            {
                if (index > 0)
                {
                    if ((task_puzzle == null) || (!mid.Equals(displaylayer.Mid_img)))
                    {
                        if(task_puzzle != null)
                        {
                            if(task_puzzle.Status != TaskStatus.RanToCompletion)
                            {
                                tokenSource.Cancel();
                            }
                        }
                        mid.X = displaylayer.Mid_img.X;
                        mid.Y = displaylayer.Mid_img.Y;
                        start[0] = mid.X - ((hang - 1) / 2);
                        start[1] = mid.Y - ((lie - 1) / 2);
                        end[0] = mid.X + ((hang - 1) / 2);
                        end[1] = mid.Y + ((lie - 1) / 2);
                        if (start[0] < 0)
                        {
                            start[0] = 0;
                            end[0] = hang - 1;
                        }
                        if (start[1] < 0)
                        {
                            start[1] = 0;
                            end[1] = lie - 1;
                        }
                        if (end[0] > displaylayer.layer.hang - 1)
                        {
                            end[0] = displaylayer.layer.hang - 1;
                            start[0] = displaylayer.layer.hang - hang;
                        }
                        if (end[1] > displaylayer.layer.lie - 1)
                        {
                            end[1] = displaylayer.layer.lie - 1;
                            start[1] = displaylayer.layer.hang - lie;
                        }
                        task_puzzle = new Task<move_data>(() => Puzzle(displaylayer.layer, int.Parse(displaylayer.layer.dimension[index]), start, end, cancel));
                        task_puzzle.Start();
                    }
                }
                if (task_puzzle != null)
                {
                    if (task_puzzle.Status == TaskStatus.RanToCompletion)
                    {
                        data = task_puzzle.Result;
                        displaylayer.dimtaskimformation[index].snp = data.img;
                        displaylayer.dimtaskimformation[index].start.X = start[0];
                        displaylayer.dimtaskimformation[index].start.Y = start[1];
                        displaylayer.dimtaskimformation[index].end.X = end[0];
                        displaylayer.dimtaskimformation[index].end.Y = end[1];
                        displaylayer.dimtaskimformation[index].mid.X = mid.X;
                        displaylayer.dimtaskimformation[index].mid.Y = mid.Y;
                        displaylayer.dimtaskimformation[index].snp = data.img;
                        displaylayer.dimtaskimformation[index].pos[0] = data.x;
                        displaylayer.dimtaskimformation[index].pos[1] = data.y;
                    }
                    displaylayer.dimtaskimformation[index].status = task_puzzle.Status;
                }
            }
        }
    }
}
